//
//  RouScanQRViewController.swift
//  ONESwift
//
//  Created by wangkun on 2017/7/10.
//  Copyright © 2017年 wangkun. All rights reserved.
//

import UIKit
import AVFoundation

//rou_make_qr
public let Rou_scan_qr = RouScanQRViewController()

open class RouScanQRViewController: BaseViewController {
    
    public typealias ScanQRBlock = (_ string: String) -> Void
    
    fileprivate let btnAlbum = UIButton(type: .custom)
    fileprivate var scanBlock: ScanQRBlock?
    
    fileprivate var alertView: UIAlertController!
    fileprivate var viewScan : ScanCaptureView!
    fileprivate var nav: UINavigationController!

    override open func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white
        self.showBackButton()
        self.title = "二维码/条码扫描"
        
        btnAlbum.titleLabel?.font = UIFont.systemFont(ofSize: 14)
        btnAlbum.addTarget(self, action: #selector(chooseImage), for: .touchUpInside)
        btnAlbum.setTitleColor(UINavigationBar.appearance().tintColor, for: .normal)
        btnAlbum.setTitle("相册", for: .normal)
        btnAlbum.sizeToFit()
        self.setNavButton(loc: .right, btns: [btnAlbum])
        
        self.initScanView()
    }
    
    override func backButtonClick() {
        self.dismiss(animated: false, completion: nil)
    }
    
    /// 初始化扫描界面
    func initScanView() {
        let authorStaus = AVCaptureDevice.authorizationStatus(for: .video)
        if [authorStaus == .restricted, authorStaus == .denied].contains(true){
            if self.alertView != nil {
                self.alertView = nil
            }
            self.alertView = UIAlertController.init(title: "温馨提示", message: "相机权限受限，请在设置->隐私->相机 中进行设置！", preferredStyle: .alert)
            let cancelAction = UIAlertAction.init(title: "取消", style: .cancel, handler: { (cancelaction) in
                
            })
            let setAction = UIAlertAction.init(title: "去设置", style: .default, handler: { (setaction) in
                let url = URL(string: UIApplicationOpenSettingsURLString)!
                if UIApplication.shared.canOpenURL(url) {
                    UIApplication.shared.openURL(url)
                }
            })
            self.alertView?.addAction(cancelAction)
            self.alertView?.addAction(setAction)
            self.present(self.alertView!, animated: true, completion: nil)
            return
        }
        
        viewScan = ScanCaptureView()
        viewScan.scanValueBlock { (string) in
            self.scanBlock?(string ?? "")
        }
        viewScan.backgroundColor = UIColor.black
        self.view.addSubview(viewScan)
        viewScan.snp.makeConstraints({ (make) in
            make.edges.equalTo(self.view)
        })
    }
    
    /// 选择图片
    @objc public func chooseImage() {
        let picker = UIImagePickerController()
        picker.sourceType = UIImagePickerControllerSourceType.photoLibrary
        picker.delegate = self;
        picker.allowsEditing = true
        present(picker, animated: true, completion: nil)
    }
    
    /// 开始扫描
    ///
    /// - Parameters:
    ///   - viewController: 来源viewController
    ///   - completeBlock:  block返回
    public func scan(_ viewController: UIViewController?, _ completeBlock: @escaping ScanQRBlock) {
        if viewController != nil {
            if nav == nil {
                nav = UINavigationController(rootViewController: self)
                nav.navigationBar.isTranslucent = false
            }
            self.scanBlock = completeBlock
            viewController?.present(nav, animated: false, completion: {})
        }
    }
    
    /// 打开对应的ViewController
    public func openViewController(_ viewController: UIViewController, _ animated: Bool = true) {
        self.navigationController?.pushViewController(viewController, animated: animated)
    }
    
    func alertScanString(_ string: String) {
        let alert = UIAlertView(title: "扫描结果", message: string, delegate: self, cancelButtonTitle: "关闭")
        alert.show()
    }
    
    /// 重新开始扫描
    func rescanQR() {
        viewScan.start()
    }
    
    //View将要出现的时候重新扫描
    override open func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.viewScan.start()
    }
    
    override open func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.viewScan.stop()
    }

    override open func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
}

// MARK: - 弹出框委托方法
extension RouScanQRViewController: UIAlertViewDelegate {
    public func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
        rescanQR()
    }
}

// MARK: - 照片选择委托方法
extension RouScanQRViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate {
    
    public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        let image:UIImage? = info[UIImagePickerControllerEditedImage] as? UIImage
        //识别二维码
        if image != nil {
            let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])!
            let img = CIImage(cgImage: (image?.cgImage)!)
            let features = detector.features(in: img, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
            if features.count > 0 {
                let feature = features[0]
                if feature.isKind(of: CIQRCodeFeature.self) {
                    let featureTmp:CIQRCodeFeature = feature as! CIQRCodeFeature
                    
                    let string = featureTmp.messageString
                    if string != nil && (string?.count)! > 0 {
                        self.scanBlock?(string ?? "")
                        self.viewScan?.stop()
                    }
                }
            }
            
        }
        picker.dismiss(animated: true, completion: nil)
    }
    
}

//MARK: - 扫描界面
fileprivate class ScanCaptureView: UIView, AVCaptureMetadataOutputObjectsDelegate {
    let device: AVCaptureDevice? = AVCaptureDevice.default(for: .video)
    
    var input : AVCaptureDeviceInput!
    var outPut : AVCaptureMetadataOutput!
    
    var captureSession : AVCaptureSession!
    var videoPreviewLayer : AVCaptureVideoPreviewLayer?
    
    var lastResult = Bool()
    var isAnmotion = false
    
    //设置四周的View
    var viewShade : QRShadeView!
    
    //扫描区域的相框
    var leftTopLayer = CAShapeLayer()
    var rightTopLayer = CAShapeLayer()
    var leftBottomLayer = CAShapeLayer()
    var rightBottomLayer = CAShapeLayer()
    
    typealias QRValueBlock = (_ string: String?) -> Void
    fileprivate var valueBlock: QRValueBlock?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        //创建扫描视图
        self.creatCapture()
        
        viewShade = QRShadeView()
        viewShade.backgroundColor = UIColor.clear
        self.addSubview(viewShade)
        viewShade.snp.makeConstraints({ (make) in
            make.edges.equalTo(self)
        })
    }
    
    deinit {
        removeAllN(self)
    }
    
    func scanValueBlock(_ block: @escaping QRValueBlock) {
        valueBlock = block
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        //设置扫描区域
//        if let rect = viewShade.scanRect {
//            self.creatScanZone(rect)
//        }
    }
    //MARK: ---创建扫描区域
    func creatScanZone(_ rect: CGRect) {
        let x = (Device.Height - rect.height) / 2 / Device.Height
        let y = (Device.Width - rect.width) / 2 / Device.Width
        let width = rect.height / Device.Height
        let height = rect.width / Device.Width
        outPut.rectOfInterest = CGRect(x: x, y: y, width: width, height: height)
    }
    
    //MARK: ---创建扫描需要的条件
    func creatCapture() {
        self.captureSession = AVCaptureSession()
        self.captureSession?.sessionPreset = .high
        //创建输入流
        guard device != nil else {
            print("device为空")
            return
        }
        do {
            input = try AVCaptureDeviceInput(device: device!)
        } catch let error as NSError{
            print("AVCaptureDeviceInput(): \(error)")
        }
        if input != nil {
            self.captureSession?.addInput(input)
        }
        
        outPut = AVCaptureMetadataOutput()
        if device == nil {
            return
        }
        //参数设置
        outPut.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        self.captureSession?.addOutput(outPut)
        
        //设置元数据类型（二维码和条形码都支持）
        outPut.metadataObjectTypes = [.qr, .ean13, .ean8, .code128]
        
        //设置采集的质量
        self.captureSession?.sessionPreset = .high
        self.videoPreviewLayer = AVCaptureVideoPreviewLayer.init(session: self.captureSession)
        
        //layer进行裁剪
        self.videoPreviewLayer?.videoGravity = .resize
        self.videoPreviewLayer?.frame = CGRect(x: 0, y: 0, width: Device.Width, height: Device.Height)//self.layer.bounds
        self.layer.insertSublayer(self.videoPreviewLayer!, at: 0)
        
        //设置聚焦(不是说所有的设备都支持，所以需要判断)
        if device!.isFocusPointOfInterestSupported && device!.isFocusModeSupported(.autoFocus) {
            do {
                try self.input?.device.lockForConfiguration()
                self.input?.device.focusMode = .autoFocus//AVCaptureFocusMode.continuousAutoFocus
                self.input?.device.unlockForConfiguration()
            } catch let error as NSError {
                print("device.lockForConfiguration(): \(error)")
            }
        }
    }
    
    //MARK: ---点击开灯按钮的事件
    func turnOnOrOffWigthLight(_ sender : UIButton) {
        sender.isSelected = sender.isSelected ? false : true
        self.theLightIsON(sender.isSelected)
    }
    
    //MARK: ---开灯或者关灯
    func theLightIsON(_ turnLight : Bool){
        if device != nil && device!.hasTorch {
            do {
                try input?.device.lockForConfiguration()
                input?.device.torchMode = turnLight ? .on : .off
                input?.device.unlockForConfiguration()
            } catch let error as NSError {
                print("device.lockForConfiguration(): \(error)")
            }
        }
    }
    
    //MARK: ---开始扫描
    func start() {
        if Device.isSimulator {
            print("Please use real machine operation, no this function  of simulator")
        } else {
            self.captureSession?.startRunning()
            viewShade.startLineAnimation()
        }
    }
    
    //MARK: ---停止
    func stop() {
        self.captureSession?.stopRunning()
        viewShade.stopLineAnimation()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    //MARK: ---得到扫描结果
    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
        
        if metadataObjects.count > 0 {
            //扫描结果返回试图控制器进行处理
            let value = metadataObjects[0] as? AVMetadataMachineReadableCodeObject
            let string = value?.stringValue
            if string != nil && (string?.count)! > 0 {
                valueBlock?(string)
                self.stop()
            }
            
        }
    }
}

class QRShadeView: UIView {
    
    var scanRect: CGRect! {
        get{
            return viewCenter.frame
        }
    }
    
    private var viewCenter = UIView()
    private let scanAreaSize = CGSize(width: 200, height: 200)
    //扫描区域的相框
    private var leftTopLayer = CAShapeLayer()
    private var rightTopLayer = CAShapeLayer()
    private var leftBottomLayer = CAShapeLayer()
    private var rightBottomLayer = CAShapeLayer()
    //移动的线条
    private var lineImage: UIImageView!
    private var timer = Timer()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.isUserInteractionEnabled = false
        viewCenter = UIView()
        viewCenter.clipsToBounds = true
        viewCenter.backgroundColor = UIColor.clear
        self.addSubview(viewCenter)
        viewCenter.snp.makeConstraints({ (make) in
            make.size.equalTo(scanAreaSize)
            make.centerX.equalTo(self)
            make.centerY.equalTo(self).offset(-10)
        })
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        self.setShade()
        self.setScanBorder()
        self.creatDrawLine()
    }
    
    func setShade() {
        //整个二维码扫描界面的颜色
        let shadeRect = CGRect(x: 0, y: 0, width: Device.Width, height: Device.Height)
        //中间清空的矩形框
        let scanRect = viewCenter.frame
        
        let ctx = UIGraphicsGetCurrentContext()
        ctx?.setFillColor(red: 40 / 255.0,green: 40 / 255.0,blue: 40 / 255.0,alpha: 0.4);
        ctx?.fill(shadeRect);
        //清除中间区域
        ctx?.clear(scanRect)
        //设置清除区域边框线条
        ctx?.stroke(scanRect)
        ctx?.setStrokeColor(UIColor.white.cgColor)
        ctx?.setLineWidth(0.8)
        ctx?.addRect(scanRect)
        ctx?.strokePath()
    }
    
    //MARK: ---设置扫描区域的线框
    func setScanBorder() {
        let scanRect = viewCenter.frame
        leftTopLayer.removeFromSuperlayer()
        rightTopLayer.removeFromSuperlayer()
        leftBottomLayer.removeFromSuperlayer()
        rightBottomLayer.removeFromSuperlayer()
        //左上角的框
        let leftTopBezierPath = UIBezierPath()
        leftTopBezierPath.move(to: CGPoint(x: scanRect.minX + 15, y: scanRect.minY - 2))
        leftTopBezierPath.addLine(to: CGPoint(x: scanRect.minX - 2, y: scanRect.minY - 2))
        leftTopBezierPath.addLine(to: CGPoint(x: scanRect.minX - 2, y: scanRect.minY + 15))
        leftTopLayer.path = leftTopBezierPath.cgPath
        leftTopLayer.lineWidth = 4
        leftTopLayer.strokeColor = UIColor.green.cgColor
        leftTopLayer.fillColor = UIColor.clear.cgColor
        self.layer.addSublayer(leftTopLayer)
        
        //右上角的框
        let rightTopBezierPath = UIBezierPath()
        rightTopBezierPath.move(to: CGPoint(x: scanRect.maxX - 15, y: scanRect.minY - 2))
        rightTopBezierPath.addLine(to: CGPoint(x: scanRect.maxX + 2, y: scanRect.minY - 2))
        rightTopBezierPath.addLine(to: CGPoint(x: scanRect.maxX + 2, y: scanRect.minY + 15))
        rightTopLayer.path = rightTopBezierPath.cgPath
        rightTopLayer.lineWidth = 4
        rightTopLayer.strokeColor = UIColor.green.cgColor
        rightTopLayer.fillColor = UIColor.clear.cgColor
        self.layer.addSublayer(rightTopLayer)
        
        //左下角
        let leftBottomBezierPath = UIBezierPath()
        leftBottomBezierPath.move(to: CGPoint(x: scanRect.minX + 15, y: scanRect.maxY + 2))
        leftBottomBezierPath.addLine(to: CGPoint(x: scanRect.minX - 2, y: scanRect.maxY + 2))
        leftBottomBezierPath.addLine(to: CGPoint(x: scanRect.minX - 2, y: scanRect.maxY - 15))
        leftBottomLayer.path = leftBottomBezierPath.cgPath
        leftBottomLayer.lineWidth = 4
        leftBottomLayer.strokeColor = UIColor.green.cgColor
        leftBottomLayer.fillColor = UIColor.clear.cgColor
        self.layer.addSublayer(leftBottomLayer)
        
        //右下角
        let rightBottomBezierPath = UIBezierPath()
        rightBottomBezierPath.move(to: CGPoint(x: scanRect.maxX + 2, y: scanRect.maxY - 15))
        rightBottomBezierPath.addLine(to: CGPoint(x: scanRect.maxX + 2, y: scanRect.maxY + 2))
        rightBottomBezierPath.addLine(to: CGPoint(x: scanRect.maxX - 15, y: scanRect.maxY + 2))
        rightBottomLayer.path = rightBottomBezierPath.cgPath
        rightBottomLayer.lineWidth = 4
        rightBottomLayer.strokeColor = UIColor.green.cgColor
        rightBottomLayer.fillColor = UIColor.clear.cgColor
        self.layer.addSublayer(rightBottomLayer)
    }
    
    //MARK: ---扫描线
    func creatDrawLine() {
        if self.lineImage == nil {
            self.lineImage = UIImageView()
            viewCenter.addSubview(self.lineImage!)
            self.lineImage?.snp.remakeConstraints({ (make) in
                make.height.equalTo(2)
                make.top.left.right.equalTo(UIEdgeInsets.zero)
            })
            viewCenter.layoutIfNeeded()
            
            let gradientLayer = CAGradientLayer()
            gradientLayer.frame = self.lineImage.bounds
            //设置渐变的主颜色
            gradientLayer.colors = [UIColor.clear.cgColor, ColorFromRGB(15, 210, 0, 0.4).cgColor, ColorFromRGB(15, 210, 0).cgColor, ColorFromRGB(15, 210, 0).cgColor, ColorFromRGB(15, 210, 0, 0.4).cgColor, UIColor.clear.cgColor]
            gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
            gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
            //将gradientLayer作为子layer添加到主layer上
            self.lineImage.layer.addSublayer(gradientLayer)
            
            timer = Timer.scheduledTimer(withTimeInterval: 1, block: { (timer) in
                UIView.animate(withDuration: timer.timeInterval, animations: {
                    self.lineImage?.snp.remakeConstraints({ (make) in
                        make.height.equalTo(2)
                        make.left.right.equalTo(UIEdgeInsets.zero)
                        if self.lineImage.frame.origin.y == 0 {
                            make.top.equalTo(self.viewCenter.snp.bottom).offset(-self.lineImage.frame.size.height)
                        } else {
                            make.top.equalTo(self.viewCenter)
                        }
                    })
                    self.viewCenter.layoutIfNeeded()
                })
            }, repeats: true)
            timer.fireDate = Date()
        }
    }
    
    //MARK: ---暂停动画的方法
    func stopLineAnimation() {
        timer.fireDate = Date.distantFuture
    }
    
    //MARK: ---继续动画的方法
    func startLineAnimation() {
        timer.fireDate = Date()
    }
}
